/**
 * jquery.dlmenu.js v1.0.1
 * http://www.codrops.com
 *
 * Licensed under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 * 
 * Copyright 2013, Codrops
 * http://www.codrops.com
 */;
(function ($, window, undefined) {

    'use strict';

    // global
    var Modernizr = window.Modernizr,
        $body     = $('body');

    $.DLMenu           = function (options, element) {
        this.$el = $(element);
        this._init(options);
    };

    // the options
    $.DLMenu.defaults  = {
        // classes for the animation effects
        animationClasses: {
            classin : 'dl-animate-in-1',
            classout: 'dl-animate-out-1'
        },
        // callback: click a link that has a sub menu
        // el is the link element (li); name is the level name
        onLevelClick    : function (el, name) {
            return false;
        },
        // callback: click a link that does not have a sub menu
        // el is the link element (li); ev is the event obj
        onLinkClick     : function (el, ev) {
            return false;
        }
    };

    $.DLMenu.prototype = {
        _init      : function (options) {

            // options
            this.options = $.extend(true, {}, $.DLMenu.defaults, options);
            // cache some elements and initialize some variables
            this._config();

            var animEndEventNames  = {
                    'WebkitAnimation': 'webkitAnimationEnd',
                    'OAnimation'     : 'oAnimationEnd',
                    'msAnimation'    : 'MSAnimationEnd',
                    'animation'      : 'animationend'
                },
                transEndEventNames = {
                    'WebkitTransition': 'webkitTransitionEnd',
                    'MozTransition'   : 'transitionend',
                    'OTransition'     : 'oTransitionEnd',
                    'msTransition'    : 'MSTransitionEnd',
                    'transition'      : 'transitionend'
                };
            // animation end event name
            this.animEndEventName  = animEndEventNames[Modernizr.prefixed('animation')] + '.dlmenu';
            // transition end event name
            this.transEndEventName = transEndEventNames[Modernizr.prefixed('transition')] + '.dlmenu',
            // support for css animations and css transitions
            this.supportAnimations = Modernizr.cssanimations,
            this.supportTransitions = Modernizr.csstransitions;

            this._initEvents();

        },
        _config    : function () {
            this.open       = false;
            this.$trigger   = this.$el.children('.dl-trigger');
            this.$menu      = this.$el.children('ul.dl-menu');
            this.$menuitems = this.$menu.find('li:not(.dl-back)');
            this.$el.find('ul.dl-submenu').prepend('<li class="dl-back"><a href="#">Back</a></li>');
            this.$back = this.$menu.find('li.dl-back');
        },
        _initEvents: function () {

            var self = this;

            this.$trigger.on('click.dlmenu', function () {

                if (self.open) {
                    self._closeMenu();
                } else {
                    self._openMenu();
                }
                return false;

            });

            this.$menuitems.on('click.dlmenu', function (event) {
                var window_width = $(window).width();
                if (window_width <= 992) {
                    event.stopPropagation();

                    var $item    = $(this),
                        $submenu = $item.children('ul.dl-submenu');

                    if ($submenu.length > 0) {

                        var $flyin           = $submenu.clone().css('opacity', 0).insertAfter(self.$menu),
                            onAnimationEndFn = function () {
                                self.$menu.off(self.animEndEventName).removeClass(self.options.animationClasses.classout).addClass('dl-subview');
                                $item.addClass('dl-subviewopen').parents('.dl-subviewopen:first').removeClass('dl-subviewopen').addClass('dl-subview');
                                $flyin.remove();
                            };

                        setTimeout(function () {
                            $flyin.addClass(self.options.animationClasses.classin);
                            self.$menu.addClass(self.options.animationClasses.classout);
                            if (self.supportAnimations) {
                                self.$menu.on(self.animEndEventName, onAnimationEndFn);
                            } else {
                                onAnimationEndFn.call();
                            }

                            self.options.onLevelClick($item, $item.children('a:first').text());
                        });

                        return false;

                    } else {
                        self.options.onLinkClick($item, event);
                    }
                }
            });

            this.$back.on('click.dlmenu', function (event) {

                var $this    = $(this),
                    $submenu = $this.parents('ul.dl-submenu:first'),
                    $item    = $submenu.parent(),
                    $flyin   = $submenu.clone().insertAfter(self.$menu);

                var onAnimationEndFn = function () {
                        self.$menu.off(self.animEndEventName).removeClass(self.options.animationClasses.classin);
                        $flyin.remove();
                    };

                setTimeout(function () {
                    $flyin.addClass(self.options.animationClasses.classout);
                    self.$menu.addClass(self.options.animationClasses.classin);
                    if (self.supportAnimations) {
                        self.$menu.on(self.animEndEventName, onAnimationEndFn);
                    } else {
                        onAnimationEndFn.call();
                    }

                    $item.removeClass('dl-subviewopen');

                    var $subview = $this.parents('.dl-subview:first');
                    if ($subview.is('li')) {
                        $subview.addClass('dl-subviewopen');
                    }
                    $subview.removeClass('dl-subview');
                });

                return false;

            });

        },
        closeMenu  : function () {
            if (this.open) {
                this._closeMenu();
            }
        },
        _closeMenu : function () {
            var self              = this,
                onTransitionEndFn = function () {
                    self.$menu.off(self.transEndEventName);
                    self._resetMenu();
                };

            this.$menu.removeClass('dl-menuopen');
            this.$menu.addClass('dl-menu-toggle');
            this.$trigger.removeClass('dl-active');

            if (this.supportTransitions) {
                this.$menu.on(this.transEndEventName, onTransitionEndFn);
            } else {
                onTransitionEndFn.call();
            }

            this.open = false;
        },
        openMenu   : function () {
            if (!this.open) {
                this._openMenu();
            }
        },
        _openMenu  : function () {
            var self = this;
            // clicking somewhere else makes the menu close
            $body.off('click').on('click.dlmenu', function () {
                self._closeMenu();
            });
            this.$menu.addClass('dl-menuopen dl-menu-toggle').on(this.transEndEventName, function () {
                $(this).removeClass('dl-menu-toggle');
            });
            this.$trigger.addClass('dl-active');
            this.open = true;
        },
        // resets the menu to its original state (first level of options)
        _resetMenu : function () {
            this.$menu.removeClass('dl-subview');
            this.$menuitems.removeClass('dl-subview dl-subviewopen');
        }
    };

    var logError = function (message) {
            if (window.console) {
                window.console.error(message);
            }
        };

    $.fn.dlmenu = function (options) {
        if (typeof options === 'string') {
            var args = Array.prototype.slice.call(arguments, 1);
            this.each(function () {
                var instance = $.data(this, 'dlmenu');
                if (!instance) {
                    logError("cannot call methods on dlmenu prior to initialization; " + "attempted to call method '" + options + "'");
                    return;
                }
                if (!$.isFunction(instance[options]) || options.charAt(0) === "_") {
                    logError("no such method '" + options + "' for dlmenu instance");
                    return;
                }
                instance[options].apply(instance, args);
            });
        } else {
            this.each(function () {
                var instance = $.data(this, 'dlmenu');
                if (instance) {
                    instance._init();
                } else {
                    instance = $.data(this, 'dlmenu', new $.DLMenu(options, this));
                }
            });
        }
        return this;
    };

})(jQuery, window);